/**
 * 
 */

package com.wutianyi.maven.plugins;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;

import com.wutianyi.maven.constants.ModeEnum;
import com.wutianyi.maven.constants.ResourceLoadType;
import com.wutianyi.maven.properties.ConfigProperties;
import com.wutianyi.maven.xml.ParserXmlDom4j;

/**
 * @author wutianyi
 *@goal autoconfig
 */
public class AutoConfigMojo extends AbstractMojo {

	/**
	 * 定义config的模式，是开发还是线上
	 * 
	 * @parameter expression="${autoconfig.mode}" default-value="develop"
	 */
	private String				mode;

	/**
	 * config xml 文件的地址
	 * 
	 * @parameter expression="${autoconfig.config_xml_path}" default-value="autoconfig/autoconfig.xml"
	 * 
	 */
	private String				configXmlPath;

	/**
	 * config properties 文件存放的路径
	 * 
	 * @parameter expression="${autoconfig.config_properties_path}"
	 */
	private String				configPropertiesPath;

	/**
	 * 定义加载文件的方式
	 * 
	 * @parameter expression="${autoconfig.resource_load_type}" default-value="classpath"
	 * 
	 */
	private String				resourceLoadType;

	/**
	 * 当定义加载资源的方式为文件方式的时候，需要指定到那个目录下去加载文件
	 * 如果制定加载方式为file但是没有制定，则会初始化为当前用户跟目录下
	 * 
	 * @parameter expression="${autoconfig.resource_load_path}"
	 */
	private String				resourceLoadPath;

	private VelocityEngine		velocityEngine;
	private ParserXmlDom4j		config;
	private ConfigProperties	properties;
	private VelocityContext		context;

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {

		init();
		mergeTemplate();
		destroy();
	}

	/**
	 * 关闭资源
	 */
	private void destroy() {

		if(null != properties) {
			properties.close();
		}
		
	}

	/**
	 * 渲染模板
	 */
	private void mergeTemplate() {

		Map<String, String> generatorFiles = config.getGeneratorFiles();

		if(null == generatorFiles) {
			return;
		}

		for(Entry<String, String> entry : generatorFiles.entrySet()) {
			Template template = velocityEngine.getTemplate(entry.getKey(), "utf8");
			if(null == template) {
				continue;
			}
			PrintWriter pw = null;

			try {
				pw = new PrintWriter(new FileOutputStream(new File(AutoConfigMojo.class.getResource("/").getFile(), entry.getValue())));
				template.merge(context, pw);
			}catch(FileNotFoundException e) {
				e.printStackTrace();
			} finally {
				if(pw != null) {
					
					pw.close();
				}
			}
			
		}
	}

	/**
	 * 根据相应的配置项进行初始化
	 */
	private void init() {

//		testInitOtherParameter();
		velocityEngine = new VelocityEngine();
		if(ResourceLoadType.FILE.getType().equals(resourceLoadType)) {
			if(StringUtils.isBlank(resourceLoadPath)) {
				// 如果选择了以文件的方式进行文件加载，但是又没有制定path，则默认到根目录
				resourceLoadPath = System.getProperty("user.home");
			}
			velocityEngine.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, resourceLoadPath);
		}else {
			velocityEngine.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
		}
		config = new ParserXmlDom4j(configXmlPath, false);
		if(StringUtils.isBlank(configPropertiesPath)) {
			properties = new ConfigProperties();
		}else {
			properties = new ConfigProperties(configPropertiesPath);
		}
		initContext();
	}

	/**
	 * 初始化context中的变量的值
	 */
	private void initContext() {

		context = new VelocityContext();
		context.put("mode", mode);

		Map<String, String> propertiesDefines = config.getProperties();
		Map<String, String> decriptions = config.getDescriptions();

		if(null == propertiesDefines) {
			return;
		}

		for(Entry<String, String> entry : propertiesDefines.entrySet()) {
			String key = entry.getKey();
			String defaultValue = entry.getValue();
			String description = decriptions.get(key);
			String value = properties.getProperties(key, defaultValue, description);
			context.put(key, value);
		}
	}

	/**
	 * !FIXME 需要删除
	 * 用于测试中，初始化其他的参数
	 */
	@SuppressWarnings("unused")
    private void testInitOtherParameter() {

		this.mode = ModeEnum.DEV.getValue();
		this.configXmlPath = "AUTO_META/autoconfig.xml";
		this.configPropertiesPath = "G:\\work\\config.properties";
		this.resourceLoadType = ResourceLoadType.FILE.getType();
		this.resourceLoadPath = "G:\\work\\vm";
	}

	public static void main(String[] args) throws MojoExecutionException, MojoFailureException {

		AutoConfigMojo mojo = new AutoConfigMojo();
		mojo.execute();
	}
}
